/**
 * Usage:
 * S1MUtils.alert('Head text', 'body text with ok, no callback', '<%=user.getConfig().getResourceValue(IResourceName.OK, user)%>');
 * S1MUtils.alert('Head text', 'body text - default close');
 * S1MUtils.confirm('Head text', 'body text - default buttons with callback (must have, with event))', null, null, process);
 * S1MUtils.generatePopover('popoverDiv_elementId', title_resourceValue, content_resourceValue, moreLink_resourceValue, title_resourceName, content_resourceName, moreLink_resourceName);
 */
var S1MUtils = (function($) {
  "use strict";

  var updateCursor = true;
  var _BUTTON_OK = 0;
  var _BUTTON_YES = 1;
  var _BUTTON_NO = 2;

  function _alert(title, message, buttonText, callback) {
    return S1MModal.alert(title, message, buttonText, callback);
  }

  function _confirm(title, message, noButtonText, yesButtonText, callback, dismissPrevModal, prevModalName) {
    return S1MModal.confirm(title, message, noButtonText, yesButtonText, callback, dismissPrevModal, prevModalName);
  }

  function _populateAutoCompleteList(elementId, values, separator) {
    var valuesLength = values.length;
    if (valuesLength > 0) {
      var valuesArray = values.split(separator);
      $('#' + elementId).typeahead({
        source: valuesArray,
        minLength: 1
      });
    }
  }

  function _uploadFiles(params, fileFieldIds, callbackMethod, callbackOnErrorMethod, callerWillManageModal) {
    if ( callerWillManageModal == undefined || !callerWillManageModal ) {

      /* if we're managing the modal, show the modal and setup callbacks wrapping the caller's
         callbacks to hide the modal after the upload
      */
      S1MModal.showFileUploadProgress(
                            resources[IResourceName.UPLOADING_FILE_RUI],
                            resources[IResourceName.UPLOAD_IN_PROGRESS_RUI],
                            resources[IResourceName.UPLOADING_PROGRESS_WARNING],
                            resources[IResourceName.UPLOADING_PROGRESS_TEXT],
                            null);


      var callerCallbackMethod = callbackMethod;
      var callbackMethod = function(jsonPayload) {
        if (callerCallbackMethod != undefined) {
          callerCallbackMethod(jsonPayload);
        }
        S1MModal.hideProgress();
      };

      var callerCallbackOnErrorMethod = callbackOnErrorMethod;
      var callbackOnErrorMethod = function(jsonPayload) {
        if (callerCallbackOnErrorMethod != undefined) {
          callerCallbackOnErrorMethod(jsonPayload);
        }
        S1MModal.hideProgress();
      };
    }
    window.superUploader({
      data :  params,
      fileFieldIds : fileFieldIds
    }, callbackMethod, callbackOnErrorMethod);


  }


  /**
    params - name/value pairs to send to the server
    callbackMethod - the method to call back to if call is successful, null if not needed
    callbackOnErrorMethod - a method to call if the server has a catchable error, and you want to do special processing client side.
    notificationDivId
    validationDivId
  */
  function _call(params, callbackMethod, callbackOnErrorMethod, notificationDivId, validationDivId, skipClearValidations) {
    if (!checkIfOKtodoAjax()) {
      return false;
    }

    var opts = {
      url: '/scholaroneAJAXServlet',
      type: 'post',
      data: params,
      dataType: "json"
    };

    if (params instanceof FormData) {
        opts['processData'] = false;
        opts['contentType'] = false;
      }

    populateSecurityToken(params);
    if ( this.updateCursor ) {
  $('body').css('cursor', 'wait');
    }

    var request = $.ajax(opts);

    request.done(function(jsonObj) {
      _ajaxDone(jsonObj, callbackMethod, callbackOnErrorMethod, notificationDivId, validationDivId, skipClearValidations);
    });

    request.fail(function(request, status) {
      _ajaxFail (request, status);
    });
  }

  /**
    params - name/value pairs to send to the server
    callbackMethod - the method to call back to if call is successful, null if not needed
    callbackOnErrorMethod - a method to call if the server has a catchable error, and you want to do special processing client side.
    notificationDivId
    validationDivId
  */
 function _syncCall(params, callbackMethod, callbackOnErrorMethod, notificationDivId, validationDivId, skipClearValidations) {

 	return new Promise((resolve, reject) => {

 		if (!checkIfOKtodoAjax()) {
 			return false;
 		}

 		var opts = {
 			url: '/scholaroneAJAXServlet',
 			type: 'post',
 			data: params,
 			dataType: "json"
 		};

 		if (params instanceof FormData) {
 			opts['processData'] = false;
 			opts['contentType'] = false;
 		}

 		populateSecurityToken(params);
 		var request = $.ajax(opts);
 		request.done(function(jsonObj) {
 			_syncAjaxDone(jsonObj, callbackMethod, callbackOnErrorMethod, notificationDivId, validationDivId, skipClearValidations);
 			resolve(jsonObj.payload);
 		});

 		request.fail(function(request, status) {
 			_syncAjaxFail(request, status);
 		});

 	});

 }


  function _ajaxDone(jsonObj, callbackMethod, callbackOnErrorMethod, notificationDivId, validationDivId, skipClearValidations)
  {
    if ( S1MUtils.updateCursor ) {
      $('body').css('cursor', 'default');
    }

    if (jsonObj.clientInfo) {
      if (jsonObj.clientInfo.hasErrorMessage
          || jsonObj.clientInfo.hasInfoMessage
          || jsonObj.clientInfo.hasGeneralValidationMessage
          || jsonObj.clientInfo.hasItemValidationMessage) {
        cleanUpOldMessageDivs(notificationDivId, validationDivId);
      }
      if ((skipClearValidations === undefined || !skipClearValidations)
            && jsonObj.clientInfo.hasGeneralValidationMessage) {
        cleanUpOldValidations();
      }

      _populateNotifications(jsonObj.clientInfo, notificationDivId, validationDivId);
      _populateValidationMessages(jsonObj.clientInfo);
    }

    if (jsonObj.payload) {
      if (typeof jsonObj.payload[IParameterName.STOP_NOW_MESSAGE] != 'undefined') {
        bailOut(jsonObj.payload);
      } else if (jsonObj.payload.vo) {
        populateFormData(jsonObj.payload.vo);
      } else {
        populateFormData(jsonObj.payload);
      }
    }

    if (jsonObj.success)
    {
      if (jsonObj.status == IStatus.AJAX_STATUS_SECURITY_FAILURE) {
        S1MModal.hideProgress(); //SF-29469 stop polling, if any.
        _alert(resources[IResourceName.ERROR], resources[IResourceName.SESSION_TIMEOUT_MESSAGE_NO_FAQ], null, _handleAjaxSecurityFailure); // SF 29813
      }
      else if (jsonObj.status == IStatus.AJAX_STATUS_SUCCESS) {
        if (callbackMethod) {
          callbackMethod(jsonObj.payload);
        }
      }
      else if (callbackOnErrorMethod){
        S1MModal.hideProgress(); //SF-29469 stop polling, if any.
        callbackOnErrorMethod(jsonObj.payload, jsonObj.status);
      }
    }
    else
    {
      if (jsonObj.status == IStatus.AJAX_STATUS_SECURITY_FAILURE) {
        S1MModal.hideProgress(); //SF-29469 stop polling, if any.
        _alert(resources[IResourceName.ERROR], resources[IResourceName.SESSION_TIMEOUT_MESSAGE_NO_FAQ], null, _handleAjaxSecurityFailure); // SF 29813
      } else {
        showErrorAlert();
        S1MModal.hideProgress();
      }

    }
  }
  function _syncAjaxDone(jsonObj, callbackMethod, callbackOnErrorMethod, notificationDivId, validationDivId, skipClearValidations)
  {
    if ( S1MUtils.updateCursor ) {
      $('body').css('cursor', 'default');
    }

    if (jsonObj.clientInfo) {
      if (jsonObj.clientInfo.hasErrorMessage
          || jsonObj.clientInfo.hasInfoMessage
          || jsonObj.clientInfo.hasGeneralValidationMessage
          || jsonObj.clientInfo.hasItemValidationMessage) {
        cleanUpOldMessageDivs(notificationDivId, validationDivId);
    	_populateNotifications(jsonObj.clientInfo, notificationDivId, validationDivId);
      	_populateValidationMessages(jsonObj.clientInfo);
      }
      if ((skipClearValidations === undefined || !skipClearValidations)
            && jsonObj.clientInfo.hasGeneralValidationMessage) {
        cleanUpOldValidations();
      }
  
    }

    if (jsonObj.success)
    {
      if (jsonObj.status == IStatus.AJAX_STATUS_SECURITY_FAILURE) {
        S1MModal.hideProgress(); //SF-29469 stop polling, if any.
        _alert(resources[IResourceName.ERROR], resources[IResourceName.SESSION_TIMEOUT_MESSAGE_NO_FAQ], null, _handleAjaxSecurityFailure); // SF 29813
      }
       if (jsonObj.status == IStatus.AJAX_STATUS_SUCCESS) {
        if (callbackMethod) {
          callbackMethod(jsonObj.payload);
        }
      }
       if (callbackOnErrorMethod){
        S1MModal.hideProgress(); //SF-29469 stop polling, if any.
        callbackOnErrorMethod(jsonObj.payload, jsonObj.status);
      }
    }
    else
    {
      if (jsonObj.status == IStatus.AJAX_STATUS_SECURITY_FAILURE) {
        S1MModal.hideProgress(); //SF-29469 stop polling, if any.
        _alert(resources[IResourceName.ERROR], resources[IResourceName.SESSION_TIMEOUT_MESSAGE_NO_FAQ], null, _handleAjaxSecurityFailure); // SF 29813
      } else {
        showErrorAlert();
        S1MModal.hideProgress();
      }

    }
  }
  
  // SF 29813
  function _handleAjaxSecurityFailure(event)
  {
    gotoLoginPage();
  }

  function _ajaxFail(request, status)
  {
	if ( request.responseText == IConstants.SESSION_TIMEOUT  ) {
		okToSendAjaxRequest = false;
	}
	
    if ( S1MUtils.updateCursor ) {
    	$('body').css('cursor', 'default');
    }

    S1MModal.hideProgress();
        showErrorAlert();
  }
  function _syncAjaxFail(request, status)
  {
	if ( request.responseText == IConstants.SESSION_TIMEOUT  ) {
		okToSendAjaxRequest = false;
	}
	
    if ( S1MUtils.updateCursor ) {
    	$('body').css('cursor', 'default');
    }

    S1MModal.hideProgress();
        showErrorAlert();
  }

  //used from ajax call
  function showErrorAlert(){
    _alert(resources[IResourceName.ERROR], resources[IResourceName.SUPPORT_CONTACT_MESSAGE]);
  }

  function _populateNotifications(clientInfo, notifDivId, validationDivId) {
    S1MValidation.populateNotifications(clientInfo, notifDivId, validationDivId)
  }

  function _populateValidationMessages(clientInfo) {
    S1MValidation.populateValidationMessages(clientInfo);
  }

  var cleanJsonStrForDisplay = function(str) {
    if (str != null){
      return str.replace(/\\[nrt]/g, " ");
    }else{
      return str;
    }
  };

  function cleanUpOldMessageDivs(notifDivId, validationDivId) {
    S1MValidation.cleanUpOldMessageDivs(notifDivId, validationDivId);
  }

  function cleanUpOldValidations() {
    S1MValidation.cleanUpOldValidations();
  }

  function _cleanUpOldMessages(notifDivId, validationDivId) {
    cleanUpOldMessageDivs(notifDivId, validationDivId);
    cleanUpOldValidations();
  }

  function populateFormData(clientFormData) {
    if (clientFormData) {
      $.each(clientFormData, function(key, value) {
        var myElement = $("#"+key);
        if (!myElement.length) {
          myElement = $("."+key);
           if (!myElement.length) {
             return true; //continue with the loop
           }
        }
        var myEleType = myElement.get(0).tagName.toUpperCase();
        if (myEleType == "INPUT") {
          if (myElement.get(0).type.toUpperCase() == "RADIO") {
            myEleType = "RADIO";
          } else if (myElement.get(0).type.toUpperCase() == "CHECKBOX") {
            myEleType = "CHECKBOX";
          }
        }
        switch(myEleType) {
          case('TABLE'):
            populateTable(myElement, value);
            break;
          case('SELECT'): case('MULTISELECT'):
            populateSelect(myElement, value);
            break;
          case('RADIO'): case('CHECKBOX'):
            populateRadioOrCheckBox(myElement, value);
            break;
          default:
            $("#" + key).val(value);
            break;
        }
      });
    }
  }

  // still under development.
  function populateTable(field, data){
  }

  /** Populates select dropdown from json data. Usually, assumes
  *   json VO uses id and name variables unless otherwise specified
  *   by data-field-* values on select control.
  */
  function populateSelect(select, data) {
    select.empty();

    var field = select.attr("data-json-id");
    var idField = (typeof field == "undefined" ? "id" : field);

    field = select.attr("data-json-name");
    var textField = (typeof field == "undefined" ? "name" : field);

    field = select.attr("data-json-selected");
    var selectedField = (typeof field == "undefined" ? "selected" : field);

    $.each(data, function (i, sel) {
      select.append($('<option>', {
        value     : sel[idField],
        text      : sel[textField],
        selected  : sel[selectedField] === "true",
      }));
    });
  }

  function populateRadioOrCheckBox(field, data) {
    field.prop( "checked", data.selected);
  }

  function populateSecurityToken(params) {
    if (params instanceof FormData) {
      params.append(IParameterName.AJAX_TOKEN, user.ajaxSecurityToken);
      return params;
    } else {
      var key = IParameterName.AJAX_TOKEN;
      var value = user.ajaxSecurityToken;
      params[key] = value;
      return params;
    }
  }

  function _post(path, params, method) {
    method = method || "post"; // Set method to post by default if not specified.

    // The rest of this code assumes you are not using a library.
    // It can be made less wordy if you use one.
    var form = document.createElement("form");
    form.setAttribute("method", method);
    form.setAttribute("action", path);

    for(var key in params) {
      if(params.hasOwnProperty(key)) {
        var hiddenField = document.createElement("input");
        hiddenField.setAttribute("type", "hidden");
        hiddenField.setAttribute("name", key);
        hiddenField.setAttribute("value", params[key]);

        form.appendChild(hiddenField);
      }
    }

    document.body.appendChild(form);
    form.submit();
  }

  //on init and on refresh upon Save
  function _generatePopover(divId, titleText, contentText, moreLink, titleResourceName, contentResourceName, moreLinkResourceName) {
    return S1MPopover.generatePopover(divId,
                                      titleText,
                                      contentText,
                                      moreLink,
                                      titleResourceName,
                                      contentResourceName,
                                      moreLinkResourceName);
  }

  //US-001713 S
  var _counterWords = function(textarea, spanName, maxLengthDisplay, countDisplaySpanName, maxLengthActual) {
    var value = document.getElementById(textarea).value;
    var currentLength = 0;

     if (value.length == 0) {
       $(spanName).html(0);
        $(countDisplaySpanName).removeClass("label-important");
        return;
      }
      var regex = /\s+/gi;
      var currentWordCount = value.trim().replace(regex, ' ').split(' ').length;

      //Prepare limits
      if(maxLengthActual == 'undefined' || maxLengthActual == null || maxLengthActual == 'null' || maxLengthActual == ""
        || maxLengthDisplay == 'undefined' || maxLengthDisplay == null || maxLengthDisplay == 'null' || maxLengthDisplay == ""
        || parseInt(maxLengthActual) <= parseInt(maxLengthDisplay) )
      {
        //calculates around ONE max limit value which is the greater of the two (comparing display and actual value if exist both otherwise set to zero)
        if(maxLengthDisplay == 'undefined' || maxLengthDisplay == null || maxLengthActual == 'null' || maxLengthDisplay == '') maxLengthDisplay = 0;
          if(maxLengthActual == 'undefined' || maxLengthActual == null || maxLengthActual == 'null' || maxLengthActual == '') maxLengthActual = 0;
        if(parseInt(maxLengthDisplay) > parseInt(maxLengthActual)) maxLengthActual = maxLengthDisplay;
        //if maxLengthDisplay == maxLengthActual, left as it is (can be 0 = 0, or other same values)
        //if maxLengthActual > maxLengthDisplay - this is the most 'valid' CC settings entry, left as it is, check around current values
      }

      //optional
      var fixedValue = _checkLimitCondition(textarea, parseInt(maxLengthActual), parseInt(currentWordCount), countDisplaySpanName, false, value);
      if(fixedValue != 'undefined' && fixedValue != null && fixedValue.length != 0)
      {
        currentWordCount = fixedValue.trim().replace(regex, ' ').split(' ').length;
      }
      currentLength = currentWordCount;

      _changeCounterSpanColor(countDisplaySpanName, currentLength, maxLengthDisplay, maxLengthActual);

      if(currentLength == maxLengthActual){
        $('#'+textarea).val(value.trim()); //SF-26685, don't allow to insert extra spaces after reaching limit
      }

      $(spanName).html(currentLength); //wordCount
    };

  var _counterChars = function(textarea, spanName, maxLengthDisplay, countDisplaySpanName, maxLengthActual) {

    var value = document.getElementById(textarea).value;
    var currentLength = 0;

    if (value != 'undefined' && value != null && value.length == 0) {
      $(spanName).html(0);
      $(countDisplaySpanName).removeClass("label-important");
      return;
    }

    currentLength = value.length; //SF-26675, removed trim()

    //clear and convert to CRLF as two chars
    value = _convertToCRLFPair(value);
    currentLength = value.length; //SF-26675, removed trim()

    var newCRLFLines = value.match(/(\r\n|\n|\r)/g);
    var addition = 0;
    var numCRLFPairs = 0;

    if (newCRLFLines != null && newCRLFLines != 0) {
        addition = newCRLFLines.length;
        if(addition  != null && addition != 0){
          newCRLFLines = addition * 2; //every CRLF as two chars
        }
    }
    //Prepare limits
    //by default calculates over one display limit (because not of all input fields have CC settings for 'display' and 'actual' limit
    var calcOverOneLimit = true;
    var calcOverTwoLimit = false;

    //if arrives validation for input field which in CC>Submission Conf. has two fields for insert limit (display max, actual max)
    if(maxLengthActual != 'undefined' && maxLengthActual != null && maxLengthActual != "" && maxLengthActual != 0 )
    {
      if(parseInt(maxLengthActual) > parseInt(maxLengthDisplay) )
      {
        calcOverTwoLimit = true;
        calcOverOneLimit = false;
      } //otherwise calculates around one max limit value which is the greater of the two (comparing display and actual value)
    }
    if (calcOverOneLimit) //over one limit
    {
      if(maxLengthDisplay == 'undefined' || maxLengthDisplay == null || maxLengthActual == 'null' || maxLengthDisplay == '') maxLengthDisplay = 0;
        if(maxLengthActual == 'undefined' || maxLengthActual == null || maxLengthActual == 'null' || maxLengthActual == '') maxLengthActual = 0;
      if(parseInt(maxLengthDisplay) > parseInt(maxLengthActual)) maxLengthActual = maxLengthDisplay;
      //if maxLengthDisplay == maxLengthActual, left as it is (can be 0 = 0, or other same values)
      //if maxLengthActual > maxLengthDisplay - this is the most 'valid' CC settings entry, left as it is, check around current values
    }

    _changeCounterSpanColor(countDisplaySpanName, currentLength, maxLengthDisplay, maxLengthActual);

    //prepare for setting maxLength tag's attribute
    var maxLength = maxLengthActual; //setting for maxLength attribute of input field tag
  maxLength = _setUpFieldsMaxLength(maxLength, currentLength, addition);

    $('#'+textarea).attr('maxLength', maxLength);
    $(spanName).html(currentLength);
  };

  function _setUpFieldsMaxLength(maxLength, currentLength, addition)
  {
      var isChrome = !!window.chrome && !!window.chrome.webstore;

      if(!isChrome){
      //For Firefox (TODO: to check other browsers too...)
        //it seems that for Chrome correct calculates value.length according to maxLength

      var newMaxLength = parseInt(maxLength) - addition;
        maxLength = newMaxLength;
      }
    return maxLength;
  }

  function _changeCounterSpanColor(countDisplaySpanName, currentLength, maxLengthDisplay, maxLengthActual)
  {
  //fix limits, if is not already fixed
  if(maxLengthActual == 'undefined' || maxLengthActual == null || maxLengthActual == 'null' || maxLengthActual == ""
      || maxLengthDisplay == 'undefined' || maxLengthDisplay == null || maxLengthDisplay == 'null' || maxLengthDisplay == ""
      || parseInt(maxLengthActual) <= parseInt(maxLengthDisplay) )
    {
      //calculates around ONE max limit value which is the greater of the two (comparing display and actual value if exist both otherwise set to zero)
      if(maxLengthDisplay == 'undefined' || maxLengthDisplay == null || maxLengthActual == 'null' || maxLengthDisplay == '') maxLengthDisplay = 0;
          if(maxLengthActual == 'undefined' || maxLengthActual == null || maxLengthActual == 'null' || maxLengthActual == '') maxLengthActual = 0;
        if(parseInt(maxLengthDisplay) > parseInt(maxLengthActual)) maxLengthActual = maxLengthDisplay;
        //if maxLengthDisplay == maxLengthActual, left as it is (can be 0 = 0, or other same values)
        //if maxLengthActual > maxLengthDisplay - this is the most 'valid' CC settings entry, left as it is, check around current values
    }
  //(un)color counter span
  if(currentLength < parseInt(maxLengthDisplay))
    {
      //remove highlights
    $(countDisplaySpanName).removeClass("label-warning");
      $(countDisplaySpanName).removeClass("label-important");
    }
    if(currentLength >= parseInt(maxLengthDisplay) && currentLength < parseInt(maxLengthActual))
    {
      //highlight warning yelow if reached 'display max'
      $(countDisplaySpanName).removeClass("label-important");
      $(countDisplaySpanName).addClass("label-warning");
    }
    if(currentLength >= parseInt(maxLengthActual))
    {
      //highlight to red if reached 'actual max'
      $(countDisplaySpanName).removeClass("label-warning");
      $(countDisplaySpanName).addClass("label-important");
    }
  }

  function _convertToCRLFPair(value)
  {
    value = value.replace(/\\r/g, '\r');
    value = value.replace(/\\n/g, '\n');
    value = value.replace(/\r\n/g, '\n');
    value = value.replace(/\r/g, '\n');
    //value = value.replace(/\t/g, '');
    value = value.replace(/\n/g, '\r\n');
    return value;
  }

  function _checkLimitCondition(textarea, maxLength, currentValueLength, spanName, isCharsCheck, arrivedCharsValue){

    if(maxLength != 0 && maxLength != null && maxLength != 'undefined'
      && currentValueLength != 0 && currentValueLength != null && currentValueLength != 'undefined')
      {
        if(isCharsCheck){
          //not in use currently
          if(currentValueLength > maxLength)
          {
            var over = currentValueLength - maxLength;
            $('#'+textarea).attr('maxLength', maxLength - over);
            var newValue = _setMaxLength(document.getElementById(textarea), maxLength - over);
          } else
          {
            $('#'+textarea).attr('maxLength', maxLength);
          }
        } else {
          if(currentValueLength > maxLength) //allow last started but reached to limit word to be inserted
          {
            //get chars count for field where we calculate around words
            var currentValueLength = arrivedCharsValue.trim().length - 1; //cut also last space
            //do not allow to insert more chars
            $('#'+textarea).attr('maxLength', currentValueLength);  //for word and KBMB counting

            //(JS event oninput() allows first to insert one char which goes over the limit before starts JS checking...)
            var currentValue = document.getElementById(textarea).value;
            $('#'+textarea).val(currentValue.trim().slice(0,-1)); //this is OK when user manual inserted values, but if we use copy-paste...

            return currentValue.trim().slice(0,-1);
          } else
          {
            $('#'+textarea).removeAttr("maxLength"); //for word and KBMB counting
          }
        }
    }
  }
  //US-001713 E

  var _setMaxLength = function(el, maxLength) {
  if(el.value.length > maxLength)
  {
    el.value = el.value.substring(0, maxLength);
  }
  }

  var _execNamedFunct = function(functName, functArg) {
    if (typeof(functName) != undefined) {
      var funct = _getFunctByName(functName);
      if (typeof funct === 'function') {
        funct(functArg);
      }
    }
  };

  var _getFunctByName = function(functName) {
    var funct;
    if (typeof(functName) != undefined && functName != null) {
      funct = window;
      var parts = functName.split(".");
      for (var i = 0; i < parts.length; i++) {
        if (typeof funct === 'object') {
          funct = funct[parts[i]];
        }
      }
    }
    return funct;
  };

  var _prepareUpload = function (fileList, index, event) {
    var IEFallback = (typeof(window.FileReader) == 'undefined') ? 1 : 0;
    if (IEFallback) {
      fileList[index] = buildIeFileObject(event);
    } else {
      if (event.target.files.length > 0)
        fileList[index] = event.target.files;
      else
        fileList[index]=null;
    }
    return fileList;
  };
  var buildIeFileObject = function (event) {
    var fileName = parseFileName(event.target.value);
    var extension ="";
    if(fileName.lastIndexOf('.') > 0){
      extension = fileName.substr(fileName.lastIndexOf('.'));
    }

      var fakeFile = {
      name :fileName ,
      size : "1",
      type : extension
    };
    var fakeFileList = [];
    fakeFileList[0] = fakeFile;
    return fakeFileList;
  };
  var parseFileName = function(name) {
    var fileName = name.match(/[^\/\\]+$/);
    return fileName[0];
  };

  var _appendFilesFromCollectedEventData = function (fileLists, formData, fileData, fileNums, forUpload) {
    var doOne = function(index, fileList) {
      if (fileList != undefined) {
        fileNums.push(index);
        var suffix = "_" + index;
        $.each(fileList, function (key, file) {
          if (forUpload == true) {
            fileData.push(IParameterName.FILE_TO_UPLOAD + suffix);
          }
          formData[IParameterName.FILE_METADATA_INDEX + suffix] = index;
          formData[IParameterName.FILE_METADATA_NAME + suffix] = file.name;
          formData[IParameterName.FILE_METADATA_SIZE + suffix] = file.size;
          formData[IParameterName.FILE_METADATA_TYPE + suffix] = file.type;
        });
      }
    };
    $.each(fileLists, doOne);
  };

  function bailOut(payload) {
    var title = resources[IResourceName.ERROR];
    var message = payload[IParameterName.STOP_NOW_MESSAGE];
    var buttonText = undefined;
    var nextPage = payload[IParameterName.NEXT_PAGE];
    var callback = function(event) { setNextPage(nextPage); };
    _alert(title, message, buttonText, callback);
  }

  return {
    ajaxDone : _ajaxDone,
    ajaxFail : _ajaxFail,
    alert : _alert,
    call : _call,
    syncCall: _syncCall,
    syncAjaxDone : _syncAjaxDone,
    syncAjaxFail : _syncAjaxFail,
    handleAjaxSecurityFailure : _handleAjaxSecurityFailure,
    cleanJsonStrForDisplay : cleanJsonStrForDisplay,
    cleanUpOldMessages : _cleanUpOldMessages,
    confirm : _confirm,
    counterChars : _counterChars,
    counterWords : _counterWords,
    convertToCRLFPair : _convertToCRLFPair,
    changeCounterSpanColor : _changeCounterSpanColor,
    setMaxLength : _setMaxLength,
    execNamedFunct : _execNamedFunct,
    generatePopover : _generatePopover,
    getFunctByName  : _getFunctByName,
    populateAutoCompleteList : _populateAutoCompleteList,
    populateNotifications : _populateNotifications,
    populateValidationMessages : _populateValidationMessages,
    post: _post,
    prepareUpload: _prepareUpload,
    appendFilesFromCollectedEventData : _appendFilesFromCollectedEventData,
    uploadFiles : _uploadFiles,
    BUTTON_YES : _BUTTON_YES,
    BUTTON_NO : _BUTTON_NO,
    BUTTON_OK : _BUTTON_OK,
    updateCursor : updateCursor
  };
})(jQuery);


/**
 * Emulate FormData for some browsers
 * MIT License
 * (c) 2010 François de Metz
 */
(function(w) {
    if (w.FormData)
        return;
    function FormData() {
        this.fake = true;
        this.boundary = "--------FormData" + Math.random();
        this._fields = [];
    }
    FormData.prototype.append = function(key, value) {
        this._fields.push([key, value]);
    }
    FormData.prototype.toString = function() {
        var boundary = this.boundary;
        var body = "";
        this._fields.forEach(function(field) {
            body += "--" + boundary + "\r\n";
            // file upload
            if (field[1].name) {
                var file = field[1];
                body += "Content-Disposition: form-data; name=\""+ field[0] +"\"; filename=\""+ file.name +"\"\r\n";
                body += "Content-Type: "+ file.type +"\r\n\r\n";
                body += file.getAsBinary() + "\r\n";
            } else {
                body += "Content-Disposition: form-data; name=\""+ field[0] +"\";\r\n\r\n";
                body += field[1] + "\r\n";
            }
        });
        body += "--" + boundary +"--";
        return body;
    }
    w.FormData = FormData;
})(window);
